package com.maddox.relax.bluetooth.ble

import android.annotation.SuppressLint
import android.bluetooth.*
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.databinding.DataBindingUtil
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.maddox.relax.R
import com.maddox.relax.bluetooth.BluetoothListAdapter
import com.maddox.relax.databinding.ActivityBleListBinding
import com.maddox.relax.util.LogUtil

import java.util.*

/**
 * Ble 低功耗蓝牙列表
 */
private const val SCAN_PERIOD: Long = 30000//扫描时间30秒

class BleListActivity : AppCompatActivity() {

    private val REQUEST_CODE = 123
    lateinit var bluetoothAdapter: BluetoothAdapter
    lateinit var bluetoothListAdapter: BluetoothListAdapter
    lateinit var bd:ActivityBleListBinding

    //连接管理,当连接上一个BLE设备时
    private var bluetoothGatt: BluetoothGatt? = null

    //缓存已经搜索展示的设备地址,去重复
    val deviceMacList = mutableListOf<String>()

    @SuppressLint("HandlerLeak")
    val handler = object : Handler() {
        override fun handleMessage(msg: Message) {


        }
    }

    //正在扫描
    private var mScanning = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        bd = DataBindingUtil.setContentView(this,R.layout.activity_ble_list)
        initView()
    }


    private fun initView() {
        //检测设备是否支持低功耗蓝牙
        checkBleSupport()
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
        if (bluetoothAdapter == null) {
            Toast.makeText(this, "该设备不支持蓝牙", Toast.LENGTH_SHORT).show()
            return
        }
        bd.header.toolbarTitle.text = "设备列表"
        bd.header.toolbarBack.setOnClickListener {
            finish()
        }
        bd.smartrefresh.setOnRefreshListener {
            //停止正在扫描
            if (mScanning)
                scanLeDevice(false)
            //重新扫描
            scanLeDevice(true)
            bd.smartrefresh.finishRefresh(1000)
        }
        bluetoothListAdapter = BluetoothListAdapter(null)
        bd.recyclerview.layoutManager = LinearLayoutManager(this)
        bd.recyclerview.addItemDecoration(DividerItemDecoration(this, DividerItemDecoration.VERTICAL))
        bd.recyclerview.adapter = bluetoothListAdapter
        bluetoothListAdapter.setOnItemClickListener { adapter, view, position ->
            //进行连接
            var item = bluetoothListAdapter.getItem(position)
            buildConnect(item)
        }
        //注册监听
        registBlueReceiver()
        if (bluetoothAdapter.isEnabled) {
            scanLeDevice(true)
        } else {
            val enableIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
            startActivityForResult(enableIntent, REQUEST_CODE)
        }


    }


    //连接到设备
    private fun buildConnect(device: BluetoothDevice) {
        bluetoothGatt = device.connectGatt(this, false, gattCallback)
    }

    //断开连接,当不使用时务必执行断开操作
    private fun disConnect() {
        //会回调到gattCallback的onConnectionStateChange方法中
        bluetoothGatt?.disconnect()
        bluetoothGatt = null

    }

    private val gattCallback = object : BluetoothGattCallback() {
        /**
         * 执行方法1: 代表连接设备的状态 ,不做耗时操作
         * @param status 连接状态 是否成功执行连接操作 BluetoothGatt.GATT_SUCCESS
         * @param newState 当前设备的连接状态 BluetoothProfile.STATE_CONNECTED(设备已经连接) BluetoothProfile.STATE_DISCONNECTED(设备已经断开连接)   当status为成功时才有意义
         *
         */
        override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
            super.onConnectionStateChange(gatt, status, newState)
            when (status) {

            }
            if (status == BluetoothGatt.GATT_SUCCESS) {
                when (newState) {
                    BluetoothProfile.STATE_CONNECTED -> {
                        LogUtil.d("设备成功建立连接:")
                    }
                    BluetoothProfile.STATE_DISCONNECTED -> {
                        //释放资源
                        gatt?.close()
                        LogUtil.d("设备断开连接:")
                    }
                }

            }
        }

        /**
         * 执行方法2: 连接成功后,进行异步 执行发现服务
         */
        override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
            super.onServicesDiscovered(gatt, status)
            //获取指定的服务
            val service = gatt?.getService(UUID.randomUUID())

            /**
             * 下面为常用操作方式 读取和写入不能同时进行,要依次进行,读取后要等到读取回调结果后才能进行下一次读取
             *  同样写入数据后,要等到写入数据回调后在进行下一次操作
             */
            //1.获取指定的服务中的读取通道 读取数据
            val readChar = service?.getCharacteristic(UUID.randomUUID())
            //调用读取指定通道中的数据,该数据读取后会回调到onCharacteristicRead方法中
            gatt?.readCharacteristic(readChar)

            //2.获取指定服务中的写入通道 写入数据
            val writeCha = service?.getCharacteristic(UUID.randomUUID())
            //封装数据
            writeCha?.setValue("数据")
            gatt?.writeCharacteristic(writeCha)

            //3.设置监听指定通道的数据变化,当BLE设备此通道的数据变化时会回调到onCharacteristicChanged()方法中
            gatt?.setCharacteristicNotification(readChar, true)
            //获取此通道的描述符,写入开启通知
            var descriptor = readChar?.getDescriptor(UUID.randomUUID())
            descriptor?.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
            gatt?.writeDescriptor(descriptor)


        }

        /**
         * 执行方法3: 在服务发现中读取了指定通道数据,结果回调到此方法
         */
        override fun onCharacteristicRead(
            gatt: BluetoothGatt?,
            characteristic: BluetoothGattCharacteristic?,
            status: Int
        ) {
            super.onCharacteristicRead(gatt, characteristic, status)
            if (status == BluetoothGatt.GATT_SUCCESS) {
                //返回读取的数据的字节数组形式
                LogUtil.d("${characteristic?.value}")
            }


        }

        /**
         * 执行方法4: 当调用了写入数据到指定通道后,会回调结果此方法,用于检测写入的数据是否合规
         * 否则重新写入
         */
        override fun onCharacteristicWrite(
            gatt: BluetoothGatt?,
            characteristic: BluetoothGattCharacteristic?,
            status: Int
        ) {
            super.onCharacteristicWrite(gatt, characteristic, status)
            val hopeVlue = "哈哈"
            //如果和期望的值不一致,重新发送
            if (!Arrays.equals(hopeVlue.toByteArray(), characteristic?.value)) {
                characteristic?.setValue(hopeVlue)
                gatt?.writeCharacteristic(characteristic)
            }

        }

        /**
         * 执行方法5: 当给指定通道设置了Ble设备数据变化主动通知到手机时 回调到此方法
         * 在此方法中可以不断读取设置了自动发送数据的通道的数据
         * 若想区分通道,可以根据 characteristic的uuid去区分干什么的
         * 也可以通过其他一些属性 比如 instanceid 等
         */
        override fun onCharacteristicChanged(
            gatt: BluetoothGatt?,
            characteristic: BluetoothGattCharacteristic?
        ) {
            super.onCharacteristicChanged(gatt, characteristic)
            //监听到数据变化
            val result = characteristic?.value
            LogUtil.d("接收到变化的数据")

        }

        /**
         * 执行方法6: 当向指定通道写入描述参数时,写入结果会回调到此方法
         */
        override fun onDescriptorWrite(
            gatt: BluetoothGatt?,
            descriptor: BluetoothGattDescriptor?,
            status: Int
        ) {
            super.onDescriptorWrite(gatt, descriptor, status)
        }
    }


    /**
     * 查找BLE设备
     */
    private fun scanLeDevice(enable: Boolean) {
        //清除缓存
        deviceMacList.clear()
        bluetoothListAdapter.data.clear()
        bluetoothListAdapter.notifyDataSetChanged()
        //执行扫描操作
        when (enable) {
            true -> {
                handler.postDelayed({
                    mScanning = false
                    bluetoothAdapter.stopLeScan(leScanCallback)
                }, SCAN_PERIOD)
                mScanning = true
                bluetoothAdapter.startLeScan(leScanCallback)
            }
            false -> {
                mScanning = false
                bluetoothAdapter.stopLeScan(leScanCallback)
            }
        }
    }

    /**
     * 查找BLE设备的回调
     */
    private val leScanCallback = BluetoothAdapter.LeScanCallback { device, rssi, scanRecord ->
        runOnUiThread {
            if (device.name != null) {
                if (!deviceMacList.contains(device.address)) {
                    bluetoothListAdapter.addData(device)
                    deviceMacList.add(device.address)
                }
                LogUtil.d("扫描到设备:${device.name}")
            }

        }
    }

    /**
     * 连接到BLE设备的回调
     */


    private fun registBlueReceiver() {
        val filter = IntentFilter()
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED)
        registerReceiver(blueReceiver, filter)
    }

    private fun checkBleSupport() {
        packageManager.takeIf {
            !it.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
        }?.also {
            Toast.makeText(this, "当前设备不支持低功耗蓝牙", Toast.LENGTH_SHORT).show()
            finish()
        }
    }


    //设备状态监听器
    private val blueReceiver = object : BroadcastReceiver() {

        override fun onReceive(context: Context?, intent: Intent?) {
            val action = intent?.action

            when (action) {
                //绑定设备
                BluetoothDevice.ACTION_BOND_STATE_CHANGED -> {
                    //获取要绑定的设备
                    val boundDevice =
                        intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) as BluetoothDevice
                    when (boundDevice.bondState) {
                        //正在绑定
                        BluetoothDevice.BOND_BONDING -> {
                            Toast.makeText(context, "正在配对 ${boundDevice.name}", Toast.LENGTH_SHORT)
                                .show()
                            LogUtil.d("正在配对 ${boundDevice.name}")
                        }
                        BluetoothDevice.BOND_BONDED -> {
                            Toast.makeText(context, "配对完成 ${boundDevice.name}", Toast.LENGTH_SHORT)
                                .show()
                            LogUtil.d("配对完成 ${boundDevice.name}")
                        }
                        BluetoothDevice.BOND_NONE -> {
                            Toast.makeText(context, "取消配对 ${boundDevice.name}", Toast.LENGTH_SHORT)
                                .show()
                            LogUtil.d("配对完成 ${boundDevice.name}")
                        }

                    }

                }


            }

        }

    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
            //turn bluetooth successfully
            scanLeDevice(true)
        } else if (requestCode == REQUEST_CODE && resultCode == RESULT_CANCELED) {
            Toast.makeText(this, "未开启蓝牙功能,无法使用", Toast.LENGTH_SHORT).show()
        } else {
            Toast.makeText(this, "当前设备无法被检测到", Toast.LENGTH_SHORT).show()
        }
    }

    override fun onDestroy() {
        scanLeDevice(false)
        super.onDestroy()
    }

}